package com.yang.newRetail.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.base.Supplier;
import com.yang.newRetail.dao.*;
import com.yang.newRetail.global.Val;
import com.yang.newRetail.model.*;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private LikeRecordMapper likeRecordMapper;

    private static final ArrayBlockingQueue<Orders> orderArrayBlockingQueue = new ArrayBlockingQueue<>(10);

    private static final Map<String, ArrayBlockingQueue<Double>> deductionArrayBlockingQueueMap = new HashMap<>();

    private static final ReentrantLock orderLock = new ReentrantLock();

    private static final ReentrantLock likeLock = new ReentrantLock();

    private static final ThreadPoolTaskExecutor tpte = new ThreadPoolTaskExecutor();

    @Autowired
    private OrderGoodMapper orderGoodMapper;

    @Autowired
    private Val val;

    public String setResult(Integer userId) throws InterruptedException {
        Map<String, Object> message = new HashMap<>();
        message.put("case_id", "3017a7ac-861b-11ee-a27c-00163e0cd583");
        message.put("status", true);
        message.put("time", "300ms");

        message.put("userId", userId);

        val.resultQueuePut(message);

        return "ok";
    }

    public void addition(int value, Double d, Supplier<Float> f){
        System.out.println("value: " + value + " " + f.get() + " " + d);
    }

    public int afferent(Operation o){
        return o.add(1,3);
    }

    public Double quote(Joint j){
        return j.ride(1.24,3.47);
    }

    public void lambda(){
        addition(afferent((int a, int b) ->{
                    int sum = a + b;

                    return sum;
                }),
                quote((Double a, Double b) -> a + b),
                new Colon(3.44f)::getCode);
    }

    public void exec(){
        lambda();

        List al = Arrays.asList("a", "b", "c", "d");
        al.forEach(Colon::printValur);

        Consumer methodParam = Colon::printValur; //方法参数
        al.forEach(x -> methodParam.accept(x));//方法执行accept

        Map<String, Integer> items = new HashMap<>();
        items.put("BCC", 60);
        items.put("A", 10);
        items.put("B", 20);
        items.put("C", 30);
        items.put("D", 40);
        items.put("SB", 60);
        items.put("E", 50);
        items.put("F", 60);
        items.put("NBS", 60);

        items.forEach((k,v)->System.out.println("Key : " + k + " Value : " + v));

        System.out.println("count: " + items.entrySet().stream().count());

        items.keySet().stream()
                .filter(s->s.contains("B"))
                .forEach(System.out::println);

        List<Student> students = Arrays.asList(
                new Student(1, "张三", 20, 29.8, new BigDecimal(3.54)),
                new Student(2, "李四", 25, 29.5, new BigDecimal(4.54)),
                new Student(3, "赵武", 23, 30.8, new BigDecimal(5.54)),
                new Student(4, "王六", 25, 31.8, new BigDecimal(4.54)),
                new Student(5, "李大", 19, 29.8, new BigDecimal(7.54)),
                new Student(6, "徐二", 17, 21.8, new BigDecimal(8.54)),
                new Student(7, "周元", 20, 13.8, new BigDecimal(3.54))
        );

        Map<Integer, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getAge));
        Map<String, List<Student>> map1 = students.stream().collect(Collectors.groupingBy(i->i.getAge() + "_" + "年龄"));
        Map<String, List<Student>> map2 = students.stream().collect(Collectors.groupingBy(i->{
            if(i.getAge() <= 20){
                return "young";
            }else{
                return "old";
            }
        }));

        System.out.println("map: " + map);
        System.out.println("map1: " + map1);
        System.out.println("map2: " + map2);

        for (Map.Entry<Integer, List<Student>> entry : map.entrySet()) {
            System.out.println("entry: " + entry);
        }

        students = students.stream().collect(collectingAndThen(
                toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getAge))),
                ArrayList::new));
        for (Student s : students) {
            Integer size = map.get(s.getAge()).size();
            System.out.println("size: " + map.get(s.getAge()) + " " + size);
            BigDecimal alonePrice = s.getAlonePrice();
            s.setAlonePrice(alonePrice.multiply(BigDecimal.valueOf(size)));
        }
        BigDecimal reduce = students.stream().map(Student::getAlonePrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println("reduce: " + reduce);

        Map<Integer, Long> nullMap = new HashMap<>();
        Map<Long, String> longMap = new HashMap<>();
        System.out.println("nullMap: " + nullMap.get(77));
        System.out.println("longMap: " + longMap.get(nullMap.get(77)).toLowerCase());
    }

    public void streaming(){
        List<Student> students = Arrays.asList(
                new Student(1, "张三", 20, 29.8, new BigDecimal(3.54)),
                new Student(2, "李四", 25, 29.5, new BigDecimal(4.54)),
                new Student(3, "赵武", 23, 30.8, new BigDecimal(5.54)),
                new Student(4, "王六", 22, 31.8, new BigDecimal(6.54))
        );

        /**
        list 打印输出为：[
        Student(id=1, name=张三, age=20, score=29.8),
                Student(id=2, name=李四, age=25, score=29.5),
                Student(id=3, name=赵武, age=23, score=30.8),
                Student(id=4, name=王六, age=22, score=31.8)
               ]
         */

        /**
         * id 作为 map 的key，name 作为 value
         * 结果集： {1=张三, 2=李四, 3=赵武, 4=王六}
         */
        Map<Integer, String> collect = students.stream()
                .collect(Collectors.toMap(Student::getId, Student::getName,  (k1, k2) -> k1));
        System.out.println("collect: " + collect);

        /**
         * id 作为 map 的 key，Student 对象作为 map 的 value
         * 结果集： {1=Student(id=1, name=张三, age=20, score=29.8),
         2=Student(id=2, name=李四, age=25, score=29.5),
         3=Student(id=3, name=赵武, age=23, score=30.8),
         4=Student(id=4, name=王六, age=22, score=31.8)}
         */
        Map<Integer, Student> collect1 = students.stream()
                .collect(Collectors.toMap(Student::getId, v -> v));
        System.out.println("collect1: " + collect1);

        /**
         * id 作为 map 的 key，Student 对象作为 map 的 value
         * 结果集： {1=Student(id=1, name=张三, age=20, score=29.8),
         2=Student(id=2, name=李四, age=25, score=29.5),
         3=Student(id=3, name=赵武, age=23, score=30.8),
         4=Student(id=4, name=王六, age=22, score=31.8)}
         */
        Map<Integer, Student> collect2 = students.stream()
                .collect(Collectors.toMap(Student::getId, Function.identity()));
        System.out.println("collect2: " + collect2);

        String typeBanner = "A=1,B=2,C=3";
        String[] typeBannerArray = typeBanner.split(",");
        System.out.println(Arrays.toString(typeBannerArray));  // [A=1, B=2, C=3]
        Map<String, String> typeBannerMap = Arrays.stream(typeBannerArray).collect(Collectors.toMap(
                (array) -> array.split("=")[0],
                (array) -> array.split("=")[1]
        ));
        System.out.println("typeBannerMap: " + typeBannerMap);

        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        /*使用函数式编程*/
        /* 第一种方式*/
        List<Integer> listAdd = list.stream().map(s -> s + 2).collect(Collectors.toList());
        System.out.println("listAdd: " + listAdd);
        /* 第二种方式*/
        List<Integer> listAdd1 = list.stream().map(OrderService::increase).collect(Collectors.toList());
        System.out.println("listAdd1: " + listAdd1);

        ArrayList<String> names = new ArrayList<String>();
        names.add("周润发");
        names.add("成龙");
        names.add("刘德华");
        names.add("吴京");
        names.add("周星驰");
        names.add("李连杰");
        names.add("胡歌");
        names.add("继国缘一");
        Stream<String> listStream = names.stream().filter(s -> s.length() == 3).limit(4);
        System.out.println("listStream: " + listStream.collect(Collectors.toList()));

        AtomicBoolean flag = new AtomicBoolean(false);
        names.stream().filter(s -> s.length() >= 3).filter(s -> s.contains("驰")).limit(4).findFirst().ifPresent(transportResource -> {
            flag.set(true);
            System.out.println("flag: " + flag.get());
        });
    }

    private static int increase(Integer temp){
        return  temp + 2;
    }

    @Transactional
    public Map<String, Object> placeAnOrder(Orders afferentOrder) throws InterruptedException {

        orderArrayBlockingQueue.put(afferentOrder);

        new Thread(new Runnable() {
            @SneakyThrows
            @Override
            public void run() {
                Orders takeOrder = orderArrayBlockingQueue.take();
                System.out.println("takeOrder：" + takeOrder);
                orderMapper.insert(takeOrder);

//                Orders uo = new Orders();
//                uo.setId("72afdf96cb5c9f4004c1d8c175ed641a");
//                uo.setUserName("线程修改1");
//                uo.setAmount(9997);
//                orderMapper.updateById(uo);

//                orderMapper.deleteById("bd728addf05b51ac39cc3cb3408f2fb1");
            }
        },"place_order_thread").start();

        new Thread(()-> {

            Orders uo = new Orders();
            uo.setId("72afdf96cb5c9f4004c1d8c175ed641a");
            uo.setUserName("线程修改 async");
            uo.setAmount(9997);
            orderMapper.updateById(uo);

        }).start();

        new Thread(()-> {

            orderMapper.deleteById("cdff607f3ba78b4dd14c5a7cebe9fcce");

        }).start();

        new Thread(()-> {

            GenericHandle<OrderMapper, Orders> goo = new GenericHandle<>(orderMapper, new Orders());
            try {
                Orders gco = new Orders();
                gco.setStoreId("GFDHFGJGHJ988523543");
                gco.setUserId("HGKJLJKL43756876");
                gco.setUserName("泛型新增 generic");
                gco.setGoodList("23546547,745235346,6347457456,525345");
                gco.setCollectionPrice((float) 345.44);
                gco.setAmount((float) 745.44);
                GenericHandle<OrderMapper, Orders> gcoo = new GenericHandle<>(orderMapper, gco);
                gcoo.created();

                goo.delete("0fb088238ff10f22fa0418ff9a269ca1");

                Orders guo = new Orders();
                guo.setId("bac15d8915d6c72f000b9113785cdb41");
                guo.setUserName("泛型修改 generic");
                guo.setAmount((float) 5197.63);
                guo.setCollectionPrice((float) 592.765);
                GenericHandle<OrderMapper, Orders> guoo = new GenericHandle<>(orderMapper, guo);
                guoo.update();

                Orders o = goo.query("2327d0100f323f14e85be5be72a2e4b0");
                System.out.println("o：" + o);
                QueryWrapper<Orders> ow = new QueryWrapper<>();
                List<Orders> os = goo.queryAll(ow);
                System.out.println("os：" + os);

                Orders mo = new Orders();
                Orders gmo = goo.queryByGenericMethod("2327d0100f323f14e85be5be72a2e4b0", mo, orderMapper);
                System.out.println("gmo：" + gmo);
                List<Orders> gmos = goo.queryAllByGenericMethod(mo, orderMapper);
                System.out.println("gmos：" + gmos);

                Orders gmco = new Orders();
                gmco.setId("jjjjjjjjjj32534jjjjjjjj");
                gmco.setStoreId("GFDHFGJGHJ988523543");
                gmco.setUserId("HGKJLJKL43756876765");
                gmco.setUserName("泛型新增 多对多 修改 generic");
                gmco.setGoodList("23546547,745235346,6347457456,525345");
                gmco.setCollectionPrice((float) 345.44);
                gmco.setAmount((float) 745.44);
                List<String> goodIdList = new ArrayList<>();
                goodIdList.add("32534523hhbjjkhgjf修改");
                goodIdList.add("gfjhghfkoiorsdg543修改");
                goodIdList.add("gfjhfgtdf432534yhf修改");
                gmco.setGoodIdList(goodIdList);

                GenericHandleMany<OrderMapper, Orders, OrderGoodMapper, OrderGoods> ghm = new GenericHandleMany<>(orderMapper, gmco, orderGoodMapper, new OrderGoods());
//                ghm.manyCreated("goodIdList", "OrderId", "GoodId");
//                ghm.manyDelete("order_id");
                ghm.manyUpdate("goodIdList", "OrderId", "GoodId");

                HashMap<String, Orders> m = (HashMap<String, Orders>)goo.testMap("Generic Map", gco);
                System.out.println("m：" + m);

            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }

        }).start();

        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "成功");
        result.put("data", null);
        result.put("orderArrayBlockingQueue", orderArrayBlockingQueue);
        return result;
    }

    public Map<String, Object> sendStartingPointPraise(String giveActivityId) throws InterruptedException {

        ArrayBlockingQueue<Double> deductionArrayBlockingQueue = new ArrayBlockingQueue<>(20);

        double deduction = 75.22;
        for (int i = 1; i < 21; i++) {
            double d;
            if (i == 20){
                d = deduction;
            }else {
                d = new Random().nextDouble() * deduction;
            }

            deductionArrayBlockingQueue.put(d);

            deduction -= d;
        }

        deductionArrayBlockingQueueMap.put(giveActivityId, deductionArrayBlockingQueue);

        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "成功");
        result.put("data", deductionArrayBlockingQueueMap);
        return result;
    }

    public Map<String, Object> giveTheThumbsUp(String giveActivityId) throws InterruptedException {

        LikeRecord likeRecord = new LikeRecord();
        likeRecord.setUserId("");
        likeRecord.setUserName("");
        likeRecord.setActivityId(giveActivityId);
        likeRecord.setDeductionAmount(deductionArrayBlockingQueueMap.get(giveActivityId).take());
//        likeRecordMapper.insert(likeRecord);

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                LikeRecord thread_likeRecord = new LikeRecord();
                thread_likeRecord.setUserId("");
                thread_likeRecord.setUserName("");
                thread_likeRecord.setActivityId(giveActivityId);
                try {
                    thread_likeRecord.setDeductionAmount(deductionArrayBlockingQueueMap.get(giveActivityId).take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
//              likeRecordMapper.insert(thread_likeRecord);
                System.out.println("thread_likeRecord_DeductionAmount：" + thread_likeRecord.getDeductionAmount());

            }).start();
        }

        Map<String, Object> result = new HashMap<>();
        result.put("code", 200);
        result.put("message", "成功");
        result.put("data", likeRecord.getDeductionAmount());
        result.put("query", deductionArrayBlockingQueueMap);
        return result;
    }

    List<List<Map<String, String>>> skuListAll = new ArrayList<>();

    public List<Map<String, Object>> generateSpecifications(Map<String, List<String>> specMap) {

        if (skuListAll.isEmpty()) {
            for (List<String> specList : specMap.values()
            ) {
                for (String spec : specList
                ) {
                    List<Map<String, String>> skuList = new ArrayList<>();
                    Map<String, String> skuMap = new HashMap<>();
                    String key = (String) specMap.keySet().toArray()[0];
                    skuMap.put("name", key);
                    skuMap.put("value", spec);
                    skuList.add(skuMap);
                    skuListAll.add(skuList);
                }
            }
        } else {
            int length = skuListAll.size();
            for (List<String> specList : specMap.values()
            ) {
                for (int k = 0; k < specList.size() - 1; k++) {
                    for (int i = 0; i < length; i++) {
                        List<Map<String, String>> skuList = new ArrayList<>();
                        for (int j = 0; j < skuListAll.get(i).size(); j++) {
                            Map<String, String> skuMap = new HashMap<>();
                            skuMap.put("name", skuListAll.get(i).get(j).get("name"));
                            skuMap.put("value", skuListAll.get(i).get(j).get("value"));
                            skuList.add(skuMap);
                        }
                        skuListAll.add(skuList);
                    }
                }
            }

            for (List<String> specList : specMap.values()
            ) {
                int count = skuListAll.size() / specList.size();
                for (int i = 0; i < specList.size(); i++) {
                    for (List<Map<String, String>> skuList:skuListAll.subList(i*count, (i+1)*count)
                         ) {
                        Map<String, String> skuMap = new HashMap<>();
                        String key = (String) specMap.keySet().toArray()[0];
                        skuMap.put("name", key);
                        skuMap.put("value", specList.get(i));
                        skuList.add(skuMap);
                    }
                }
            }
        }

        List<Map<String, Object>> resultSkuList = new ArrayList<>();
        for (int i = 0; i < skuListAll.size(); i++) {
            Map<String, Object> spec = new HashMap<>();
            spec.put("specs", skuListAll.get(i));
            spec.put("logo", "6546457568752345"+ String.valueOf(i) +".png");
            resultSkuList.add(spec);
        }

        return resultSkuList;
    }

    public List<Map<String, Object>> generateSpecificationsMultiple(List<Map<String, List<String>>> specMapList) {

        List<List<Map<String, String>>> skuListAllMultiple = new ArrayList<>();
        
        for (Map<String, List<String>> specMap:specMapList
             ){
            if (skuListAllMultiple.isEmpty()) {
                for (List<String> specList : specMap.values()
                ) {
                    for (String spec : specList
                    ) {
                        List<Map<String, String>> skuList = new ArrayList<>();
                        Map<String, String> skuMap = new HashMap<>();
                        String key = (String) specMap.keySet().toArray()[0];
                        skuMap.put("name", key);
                        skuMap.put("value", spec);
                        skuList.add(skuMap);
                        skuListAllMultiple.add(skuList);
                    }
                }
            } else {
                int length = skuListAllMultiple.size();
                for (List<String> specList : specMap.values()
                ) {
                    for (int k = 0; k < specList.size() - 1; k++) {
                        for (int i = 0; i < length; i++) {
                            List<Map<String, String>> skuList = new ArrayList<>();
                            for (int j = 0; j < skuListAllMultiple.get(i).size(); j++) {
                                Map<String, String> skuMap = new HashMap<>();
                                skuMap.put("name", skuListAllMultiple.get(i).get(j).get("name"));
                                skuMap.put("value", skuListAllMultiple.get(i).get(j).get("value"));
                                skuList.add(skuMap);
                            }
                            skuListAllMultiple.add(skuList);
                        }
                    }
                }

                for (List<String> specList : specMap.values()
                ) {
                    int count = skuListAllMultiple.size() / specList.size();
                    for (int i = 0; i < specList.size(); i++) {
                        for (List<Map<String, String>> skuList : skuListAllMultiple.subList(i * count, (i + 1) * count)
                        ) {
                            Map<String, String> skuMap = new HashMap<>();
                            String key = (String) specMap.keySet().toArray()[0];
                            skuMap.put("name", key);
                            skuMap.put("value", specList.get(i));
                            skuList.add(skuMap);
                        }
                    }
                }
            }
        }

        List<Map<String, Object>> resultSkuList = new ArrayList<>();
        for (int i = 0; i < skuListAllMultiple.size(); i++) {
            Map<String, Object> spec = new HashMap<>();
            spec.put("specs", skuListAllMultiple.get(i));
            spec.put("logo", "6546457568752345"+ String.valueOf(i) +".png");
            resultSkuList.add(spec);
        }

        return resultSkuList;
    }

    public Integer asynchronousComputing() throws InterruptedException {
        final Integer[] s = {0};
        final Integer[] y = {0};

//        AtomicInteger cnt = new AtomicInteger(0);
//        AtomicInteger cnt1 = new AtomicInteger(0);
//        AtomicInteger cnt2 = new AtomicInteger(0);

        ReentrantLock reentrantLock = new ReentrantLock();
        CountDownLatch latch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            int p = i;
            new Thread(new Runnable() {
                @SneakyThrows
                @Override
                public void run() {

                    reentrantLock.lock();
                    s[0] += 1;
                    y[0] += s[0];
                    latch.countDown();
                    reentrantLock.unlock();

                }
            }, "computing_thread" + String.valueOf(p)).start();

//            new Thread(new Runnable() {
//                public void run() {
//                    s[0] += 1;
//
//                    latch.countDown();
//                }
//            }).start();
        }

        new Thread(()-> {
            for(int i=0;i<100000;i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("一边听歌" + i);
//                latch.countDown();
            }
        }
        ).start();

        latch.await();

        return y[0];
    }
}
